home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / inthook.asc < prev    next >
Encoding:
Text File  |  1991-12-17  |  13.0 KB  |  362 lines

  1. _USING DPMI TO HOOK INTERRUPTS IN WINDOWS 3_
  2. by Walter Oney
  3.  
  4. [LISTING ONE]
  5.  
  6. #############################################################################
  7. #  MAKE file for INTHOOK example and helper programs.
  8. #  By Walter Oney.    Use with Microsoft C 6.0A & MASM 5.1 (or compatibles)
  9. #############################################################################
  10.  
  11. all: inthook.exe int60.com int61.com
  12.  
  13. inthook.obj: inthook.c
  14.     cl -AS -Zlipe -c -Gsw2 -Ows -W3 inthook.c >inthook.err
  15. inthook.exe: inthook.obj
  16.     link /noe /nod /co /m inthook,inthook,inthook,slibcaw libw,inthook;
  17.     rc inthook.exe
  18.     mapsym inthook
  19. int60.com: int60.asm
  20.     masm int60;
  21.     link int60;
  22.     exe2bin int60 int60.com
  23. int61.com: int61.asm
  24.     masm int61;
  25.     link int61;
  26.     exe2bin int61 int61.com
  27.  
  28.  
  29.  
  30.  
  31. [LISTING TWO]
  32.  
  33. /****************************************************************************
  34.  * INTHOOK.C   -- by Walter Oney                  Use with Microsoft C 6.0A.
  35.  * Sample app illustrating interrupt hooking in Win3 using DPMI 0.9 services
  36.  ****************************************************************************/
  37.  
  38. /* Include files */
  39. #include "windows.h"            /* MS windows dcls */
  40. #include "dos.h"                /* for FP_SEG, FP_OFF */
  41.  
  42. /* Local procedures and data */
  43.      static HANDLE hInst ;  /* current instance handle */
  44.      static HWND hMyWindow ;    /* handle for our window */
  45.      static void (interrupt far *org60)() ; /* original INT 60 handler */
  46.      static void (far *callback)() ; /* real mode callback address */
  47.      typedef struct
  48.     {           /* real mode callback */
  49.     unsigned long edi, esi, ebp, junk, ebx, edx, ecx, eax ;
  50.     unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss ;
  51.     } CBSTRUCT ;        /* real mode callback */
  52.      CBSTRUCT cb60 ;        /* callback for INT 60 handling */
  53.  
  54.      static void hook60(void) ; /* hook INT 60 */
  55.      static void unhook60(void) ; /* unhook INT 60 */
  56.      static void interrupt far int60() ; /* interrupt handler */
  57.  
  58. /**********************************************************************/
  59. /* Main window procedure: */
  60.      LONG FAR PASCAL MainWndProc
  61.     (HWND hWnd,     /* window handle */
  62.     WORD iMessage,      /* message code */
  63.     WORD wParam,        /* 1st parameter */
  64.     LONG lParam)        /* 2d parameter */
  65.     {           /* MainWndProc */
  66. /* Local variables */
  67.     long retcode = 0 ;  /* return code */
  68. /* Text */
  69.     switch(iMessage)
  70.        {            /* process message */
  71.     case WM_CREATE:
  72.        hMyWindow = hWnd ;   /* so INT60 can find it */
  73.        hook60() ;
  74.        break ;
  75.     case WM_USER:       /* posted by int60() */
  76.        MessageBox(GetFocus(), "Wake up!", "Salutations",
  77.           MB_ICONEXCLAMATION | MB_OK) ;
  78.        break ;
  79.     case WM_DESTROY:    /* window being destroyed */
  80.        unhook60() ;
  81.        PostQuitMessage(0) ;
  82.        break ;
  83.     default:        /* some other message */
  84.        retcode = DefWindowProc(hWnd, iMessage, wParam, lParam) ;
  85.        break ;
  86.        }            /* process message */
  87.     return retcode ;
  88.     }           /* MainWndProc */
  89.  
  90. /**********************************************************************/
  91. /* Window message loop: */
  92.      int PASCAL WinMain
  93.     (HANDLE hInstance,  /* current instance */
  94.     HANDLE hPrevInstance,   /* previous instance (if any) */
  95.     LPSTR lpCmdLine,    /* command line */
  96.     int nCmdShow)       /* show window type (open/icon) */
  97.     {           /* WinMain */
  98. /* Local variables */
  99.     HWND hWnd ;     /* window handle */
  100.     MSG msg ;       /* current message */
  101.     WNDCLASS wc ;       /* template for this class */
  102. /* Text */
  103. /* Only allow one instance of the application at a time -- there's only
  104.    one interrupt vector to hook! */
  105.     if (hPrevInstance)
  106.        return FALSE ;
  107. /* Create the window class. */
  108.     wc.style = 0 ;      /* default styles */
  109.     wc.lpfnWndProc = MainWndProc ; /* window proc */
  110.     wc.cbClsExtra = 0 ; /* no extra bytes for class */
  111.     wc.cbWndExtra = 0 ; /* no extra bytes for instance */
  112.     wc.hInstance = hInstance ; /* who created the class */
  113.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION) ;
  114.     wc.hCursor = LoadCursor(NULL, IDC_ARROW) ; /* default cursor */
  115.     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
  116.     wc.lpszMenuName = NULL ; /* no menu */
  117.     wc.lpszClassName = "AppWClass" ; /* name of window class */
  118.     if (!RegisterClass(&wc))
  119.        return FALSE ;
  120. /* Create an instance of the class (i.e., our own window) */
  121.     hInst = hInstance ; /* so window proc can access it */
  122.     hWnd = CreateWindow("AppWClass",
  123.        "Interrupt Hook Sample Application",
  124.        WS_OVERLAPPEDWINDOW,
  125.        CW_USEDEFAULT,
  126.        CW_USEDEFAULT,
  127.        CW_USEDEFAULT,
  128.        CW_USEDEFAULT,
  129.        NULL, NULL, hInstance, NULL) ;
  130.     if (!hWnd)
  131.        return FALSE ;
  132.     ShowWindow(hWnd, SW_SHOWMINIMIZED) ;
  133.     UpdateWindow(hWnd) ;
  134. /* Main message loop */
  135.     while (GetMessage(&msg, NULL, NULL, NULL))
  136.        {             /* until WM_QUIT message */
  137.        TranslateMessage(&msg) ; /* xlate virtual key codes */
  138.        DispatchMessage(&msg) ; /* dispatch handler */
  139.        }             /* until WM_QUIT message */
  140.     return msg.wParam ; /* PostQuitMessage's arg */
  141.     }           /* WinMain */
  142.  
  143. /**********************************************************************/
  144. /* HOOK60 hooks software interrupt 60h in real mode, using a real-mode
  145.    callback to get control passed to int60(). */
  146.      static void hook60()
  147.     {           /* hook60 */
  148.     _asm
  149.        {
  150.        push  ds     ; save DS across call
  151.  
  152.        mov   ax, ds     ; ES:DI -> callback structure
  153.        mov   es, ax     ;   ..
  154.        mov   di, offset cb60;   ..
  155.        mov   ax, cs     ; DS:SI -> routine to call
  156.        mov   ds, ax     ;   ..
  157.        mov   si, offset int60 ; ..
  158.        mov   ax, 0303h  ; fcn 0303: allocate real mode callback
  159.        int   31h        ; issue DPMI function request
  160.  
  161.        pop   ds     ; restore DS
  162.        mov   callback, dx   ; CX:DX = callback address
  163.        mov   callback+2, cx ;   ..
  164.  
  165.        mov   bl, 60h    ; BL = interrupt number (60h)
  166.        mov   ax, 0200h  ; fcn 0200: get real mode interrupt vector
  167.        int   31h        ; issue DPMI function request
  168.        mov   org60, dx  ; CX:DX = original real mode vector
  169.        mov   org60+2, cx    ;   ..
  170.  
  171.        mov   dx, callback   ; CX:DX = new REAL MODE handler address
  172.        mov   cx, callback+2 ;   ..
  173.        mov   ax, 0201h  ; fcn 0201: set real mode interrupt vector
  174.        int   31h        ; issue DPMI fcn request
  175.        }
  176.     }           /* hook60 */
  177.  
  178. /**********************************************************************/
  179. /* UNHOOK60 restores the original interrupt 60h vector. */
  180.      static void unhook60()
  181.     {           /* unhook60 */
  182.     _asm
  183.        {
  184.        mov   dx, org60  ; CX:DX = original INT 60 vector
  185.        mov   cx, org60+2    ;   ..
  186.        mov   bl, 60h    ; BL = interrupt number (60h)
  187.        mov   ax, 0201h  ; fcn 0201: set real mode interrupt vector
  188.        int   31h        ; issue DPMI fcn request
  189.  
  190.        mov   dx, callback   ; CX:DX = real-mode callback address
  191.        mov   cx, callback+2 ;   ..
  192.        mov   ax, 0304h  ; fcn 0304: free real mode callback
  193.        int   31h        ; issue DPMI fcn request
  194.        }
  195.     }           /* unhook60 */
  196.  
  197. /**********************************************************************/
  198. /* INT60 is the interrupt handler for interrupt 60h. It gains control from
  199.    the real-mode callback address allocated by HOOK60() and uses PostMessage
  200.    to send a message to the application's window procedure. */
  201.      typedef struct
  202.     {           /* interrupt register structure */
  203.     unsigned short es, ds ;
  204.     unsigned short di, si, bp, sp, bx, dx, cx, ax ;
  205.     unsigned short flags, ip, cs ;
  206.     } IFRAME ;      /* interrupt register structure */
  207.      static void interrupt far int60(IFRAME f)
  208.     {           /* int60 */
  209.     unsigned int far *isp ; /* interrupting stack pointer */
  210. /* Simulate IRET in signalling process. */
  211.     FP_SEG(isp) = f.ds ;
  212.     FP_OFF(isp) = f.si ;
  213.     cb60.ip = isp[0] ;
  214.     cb60.cs = isp[1] ;
  215.     cb60.flags = isp[2] ;
  216.     cb60.sp += 6 ;
  217. /* Post a private message leading to a message box. */
  218.     PostMessage(hMyWindow, WM_USER, NULL, NULL) ;
  219.     }           /* int60 */
  220.  
  221.  
  222.  
  223. [LISTING THREE] 
  224.  
  225. NAME        INTHOOK
  226. DESCRIPTION 'Interrupt Hook Sample Application'
  227. EXETYPE     WINDOWS
  228. STUB        'WINSTUB.EXE'
  229. CODE        PRELOAD MOVEABLE DISCARDABLE
  230. DATA        PRELOAD MOVEABLE MULTIPLE
  231. HEAPSIZE    1024
  232. STACKSIZE   5120
  233. EXPORTS
  234.     MainWndProc          @1
  235.  
  236.  
  237.  
  238. [LISTING FOUR]
  239.  
  240. ;-----------------------------------------------------------------------------
  241. ; INT60.ASM --  Signaller program for INTHOOK example app.  By Walter Oney.
  242. ;-----------------------------------------------------------------------------
  243.      name  int60
  244. int60    segment byte public 'code'
  245.      assume cs:int60, ds:int60
  246.      org   100h       ; required for .COM file usage
  247.  
  248. ; See if forwarder program is present by checking interrupt vector for 61h.
  249. begin:   mov   ax, 3561h      ; get int 61 vector address
  250.      int   21h        ;   ..
  251.      mov   ax, es         ; be sure there is one
  252.      or    ax, bx         ;   ..
  253.      jz    cantcall       ; if not, complain and quit
  254.  
  255. ; Use 2F/1685 to switch to system virtual machine and call forwarder program. 
  256. ; Note that no-one actually does an INT 61h--we simply use the vector as a 
  257. ; convenient (and facile) place to park the address of the callback
  258.      mov   ax, 1685h      ; fcn 1685: switch VM's and callback
  259.      mov   di, bx         ; ES:DI = callback address (int 61 hdlr)
  260.      mov   bx, 1          ; BX = VM to switch to (system VM)
  261.      mov   cx, 3          ; CX = .... .... .... ..11 -- wait until
  262.                   ;    interrupts enabled and critical
  263.                   ;    section unowned
  264.      xor   dx, dx         ; DX:SI = priority boost (zero)
  265.      xor   si, si         ;   ..
  266.      int   2Fh        ; switch to system VM & do INT 60
  267.  
  268. ; If the forwarder found an INT 60 handler, it saved the address beginning
  269. ; after a 3-byte JMP located at 100h. Check this in order to complain if
  270. ; the responder WinApp isn't loaded. Note that this test will sometimes
  271. ; fail because we're running asynchronously with the system VM.
  272.      mov   ax, word ptr es:[103h]; see if forwarder found an INT60 handler
  273.      or    ax, word ptr es:[105h];   ..
  274.      jz    no60       ; if not, complain about it
  275. goback:  mov   ax, 4C00h      ; terminate with errorlevel 0
  276.      int   21h        ; (does not return)
  277. cantmsg  db    'The forwarder program is not installed', 13, 10, '$'
  278. nomsg    db    'The responder WinApp is not running', 13, 10, '$'
  279. no60:    lea   dx, nomsg      ; responder not present
  280.      jmp   short complain     ;   ..
  281. cantcall:lea   dx, cantmsg    ; forwarder not present
  282. complain:mov   ah, 9          ; fcn 9: print msg in DS:DX on screen
  283.      int   21h        ;   ..
  284.      jmp   goback         ; exit
  285. int60    ends
  286.      end   begin
  287.  
  288.  
  289.  
  290.  
  291. [LISTING FIVE]
  292.  
  293. ;-----------------------------------------------------------------------------;
  294. ;    INT61.ASM -- Forwarder program for the INTHOOK example application       ;
  295. ;    Written by Walter Oney                           ;
  296. ;-----------------------------------------------------------------------------;
  297.  
  298.      name  int61
  299.      .286p
  300. int61    segment byte public 'code'
  301.      assume cs:int61, ds:int61
  302.      org   100h       ; required for .COM file usage
  303. begin:   jmp   doit       ; jump around fixed data area
  304.  
  305. vect60   dw    0, 0       ; for inspection by signaller
  306.  
  307. doit:    mov   ax, 2561h      ; hook INT 61h so INT60 can find us
  308.      lea   dx, callback   ;   from another virtual machine
  309.      int   21h        ;   ..
  310.  
  311.      lea   dx, endprog+15     ; point past all code in this module
  312.      shr   dx, 4          ; compute # paragraphs to keep
  313.      mov   ax, 3100h      ; terminate and stay resident
  314.      int   21h        ; (does not return)
  315. ;    CALLBACK is reached circuitously when INT60 does a 2F/1685 to schedule
  316. ;    it to run in the system virtual machine.
  317. callback:
  318.      push  es         ; save working registers
  319.      push  ds         ;   ..
  320.      pusha            ;   ..
  321.      mov   ax, cs         ; set DS == CS
  322.      mov   ds, ax         ;   ..
  323.  
  324.      mov   ax, 3560h      ; get current INT 60 vector address
  325.      int   21h        ;   ..
  326.      mov   vect60, bx     ; save for debugging inspection
  327.      mov   vect60+2, es   ;   ..
  328.  
  329.      mov   ax, es         ; is there a handler?
  330.      or    ax, bx         ;   ..
  331.      jz    done60         ; if not, don't signal it!
  332.      int   60h        ; issue INT 60 to wakeup WinApp
  333. done60:  popa             ; restore registers
  334.      pop   ds
  335.      pop   es         ;   ..
  336.      iret             ; return from callback to Windows
  337. endprog:              ; for 21/31 paragraph computation
  338. int61    ends
  339.      end   begin
  340.  
  341.  
  342.  
  343.  
  344. EXAMPLE 1.  
  345.  
  346.    pusha
  347.    push   ds
  348.    push   es
  349.    mov    bp,sp
  350.    mov    ax,DGROUP
  351.    mov    ds,ax
  352.    cld
  353.  
  354.    [function body]
  355.  
  356.    pop    es
  357.    pop    ds
  358.    popa
  359.    iret
  360.  
  361.  
  362.